package com.jeeplus.test.jlnu.admissionInfo.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jeeplus.test.jlnu.admissionInfo.domain.entity.AdmissionInfo;
import com.jeeplus.test.jlnu.admissionInfo.domain.entity.ImportFailLog;
import com.jeeplus.test.jlnu.admissionInfo.domain.entity.JlnuTeachingArchives;
import com.jeeplus.test.jlnu.admissionInfo.domain.entity.Supplement;
import com.jeeplus.test.jlnu.admissionInfo.domain.vo.AdmissionInfoDto;
import com.jeeplus.test.jlnu.admissionInfo.domain.vo.AdmissionInfoReqVo;
import com.jeeplus.test.jlnu.admissionInfo.domain.vo.AdmissionInfoRespVo;
import com.jeeplus.test.jlnu.admissionInfo.service.AdmissionInfoService;
import com.jeeplus.test.jlnu.archivalInfo.domain.entity.ArchivalInfo;
import com.jeeplus.test.jlnu.teachingArchive.service.AcademicInfoService;
import com.jeeplus.test.tools.resp.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "录取信息")
@RestController
@Slf4j
@RequestMapping("/admissionInfo")
public class AdmissionInfoController {

    @Autowired
    private AdmissionInfoService admissionInfoService;

    @Autowired
    private AcademicInfoService academicInfoService;


    @ApiOperation("录取信息分页查询")
    @GetMapping("/page")
    public ResponseEntity<Page<Map<String, Object>>> getAdmissionInfoPage(AdmissionInfoReqVo admissionInfoReqVo,
                                                                          @RequestParam(defaultValue = "1") int pageNum,
                                                                          @RequestParam(defaultValue = "10") int pageSize) {
        Page<AdmissionInfoRespVo> page = new Page<>(pageNum, pageSize);
        Page<Map<String, Object>> pageResult = admissionInfoService.getAdmissionInfoPage(admissionInfoReqVo, page);

        // 确保 null 值字段被填充
        List<Map<String, Object>> modifiedRecords = pageResult.getRecords().stream()
                .map(record -> {
                    Map<String, Object> modifiedRecord = new HashMap<>();
                    record.forEach((key, value) -> modifiedRecord.put(key, value != null ? value : ""));
                    return modifiedRecord;
                })
                .collect(Collectors.toList());

        Page<Map<String, Object>> modifiedPage = new Page<>(pageResult.getCurrent(), pageResult.getSize(), pageResult.getTotal());
        modifiedPage.setRecords(modifiedRecords);

        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(modifiedPage);
    }

    @ApiOperation("录取信息批量修改")
    @PostMapping("/batchUpdate")
    public R batchUpadte(@RequestBody AdmissionInfoDto admissionInfoDto) {
        if (admissionInfoDto == null || admissionInfoDto.getStudentIds() == null || admissionInfoDto.getStudentIds().isEmpty()) {
            return R.error("9999", "参数为空");
        }

        admissionInfoService.batchUpdate(admissionInfoDto.getStudentIds(), admissionInfoDto);
        return R.suc("成功");


    }

    @ApiOperation("根据学号查询全部数据")
    @GetMapping("/selectNullByStuId")
    public R selectNullByStuId(@RequestParam String stuId) {
        if (StringUtils.isEmpty(stuId)) {
            return R.error("9999", "参数为空");
        } else {
            Supplement supplement = admissionInfoService.selectNullByStuId(stuId);
            return R.suc(supplement);
        }
    }


    @ApiOperation("补充全部数据")
    @PostMapping("/supplement")
    public R supplement(@RequestBody Supplement supplement) {
        int i = admissionInfoService.updateArchival(supplement);
        if (i > 0) {
            return R.suc();
        } else {
            return R.error();
        }
    }

    @ApiOperation("录取信息批量新增功能")
    @PostMapping("/saveBatch")
    public R saveBatch(@RequestBody List<AdmissionInfo> admissionInfoRespVos) {
        int i = admissionInfoService.insertAdmissions(admissionInfoRespVos);
        if (i > 0) {
            return R.suc();
        } else {
            return R.error();
        }
    }

    @ApiOperation("录取信息数据下载")
    @PostMapping("/admissionDataDowload")
    public  ResponseEntity<byte[]> admissionDataDowload(@RequestParam("ids") List<String> ids
                                                        ,@RequestParam("exportFields")List<String> exportFields){
        return admissionInfoService.admissionDataDowload(ids,exportFields);
    }

    @ApiOperation("录取信息重新导入（只修改教学档案,同时生成失败记录）")
    @PostMapping("/importTecData")
    public R importTecData(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty() || !file.getOriginalFilename().endsWith(".xlsx")) {
            return R.error("9999", "文件为空或格式不正确");
        }
        String fileName = "";
        String realFileName = "";
        List<AdmissionInfoReqVo> tempList = new ArrayList<>(); // 存储所有数据
        List<Integer> failRecords = new ArrayList<>(); // 记录失败的行号
        List<AdmissionInfoReqVo> newList = new ArrayList<>(); // 存储失败数据

        try {
            EasyExcel.read(file.getInputStream(), AdmissionInfoReqVo.class, new AnalysisEventListener<AdmissionInfoReqVo>() {
                @Override
                public void invoke(AdmissionInfoReqVo data, AnalysisContext context) {
                    tempList.add(data);
                }

                @Override
                public void onException(Exception exception, AnalysisContext context) {
                    int rowIndex = context.readRowHolder().getRowIndex() + 1;
                    failRecords.add(rowIndex);
                    context.readRowHolder().setCurrentRowAnalysisResult(true); // 跳过当前行
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    // 解析完毕，不需要额外处理
                }
            }).sheet().doRead();
        } catch (Exception e) {
            return R.error("9999", "文件解析失败: " + e.getMessage());
        }

        // 根据失败行号索引失败数据
        for (Integer index : failRecords) {
            if (index >= 0 && index < tempList.size()) {
                newList.add(tempList.get(index));
            }
        }

        // 处理数据

        for (AdmissionInfoReqVo admissionInfo : tempList) {
            try {
                updateOrInsertRecord(admissionInfo);
            } catch (Exception e) {
                admissionInfo.setRemark("导入失败: " + e.getMessage());
                newList.add(admissionInfo);
            }
        }

        // 生成失败记录 Excel
        String failFileUrl = null;
        if (!newList.isEmpty()) {
            Map map = generateFailedRecordsExcel(newList);
            failFileUrl = map.get("filePath").toString();
            realFileName = map.get("fileName").toString();
        }

        // 存入日志
        if (failFileUrl != null) {
            ImportFailLog failLog = new ImportFailLog();
            failLog.setCreateTime(new Date());
            failLog.setMessage("失败记录文件: " + failFileUrl);
            failLog.setFileName(realFileName);
            failLog.setFileUrl(failFileUrl);
            admissionInfoService.insertImportLog(failLog);
        }

        return R.suc(failFileUrl != null ? "部分导入失败，失败文件：" + failFileUrl : "全部导入成功");
    }

    /**
     * 生成失败记录 Excel 文件
     */
    private Map generateFailedRecordsExcel(List<AdmissionInfoReqVo> failedRecords) {
        String fileNames = "failed_records_" + System.currentTimeMillis() + ".xlsx";
        String abusole = "11/import_fail_logs/";
        String filePath = "D:/11/import_fail_logs/" + fileNames;

        File file = new File(filePath);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        EasyExcel.write(filePath, AdmissionInfoReqVo.class)
                .excelType(ExcelTypeEnum.XLSX)
                .sheet("失败记录")
                .doWrite(failedRecords);
        HashMap<String, String> map = new HashMap<>();
        map.put("fileName", fileNames);
        map.put("filePath", abusole);
        return map;
    }


    private void updateOrInsertRecord(AdmissionInfoReqVo admissionInfo) {
        try {
            // 根据学号检查是否存在于 jlnu_teaching_archives 表中
            JlnuTeachingArchives existingRecord = admissionInfoService.selectByStudentId(admissionInfo.getStudentId());

            // 如果记录存在，更新记录
            if (existingRecord != null) {
                updateRecord(existingRecord, admissionInfo);
                admissionInfoService.updateById(existingRecord);
            } else {
                // 如果没有记录，插入新记录
                JlnuTeachingArchives newRecord = new JlnuTeachingArchives();
                updateRecord(newRecord, admissionInfo);
                admissionInfoService.insert(newRecord);
            }
        } catch (Exception e) {
            throw new RuntimeException("学号: " + admissionInfo.getStudentId() + " 导入失败，错误: " + e.getMessage());
        }
    }

    private void updateRecord(JlnuTeachingArchives record, AdmissionInfoReqVo admissionInfo) {
        record.setStudentId(admissionInfo.getStudentId());
        record.setArchiveCode(admissionInfo.getArchiveCode());
        record.setFullSetCode(admissionInfo.getFullSetCode());
        record.setCategoryCode(admissionInfo.getCategoryCode());
        record.setCategoryId(admissionInfo.getCategoryId());
        record.setProjectId(admissionInfo.getProjectId());
        record.setDirectoryCode(admissionInfo.getDirectoryCode());
        record.setAnnual(admissionInfo.getAnnual());
        record.setRetentionPeriodCode(admissionInfo.getRetentionPeriodCode());
        record.setInstitution(admissionInfo.getInstitution());
        record.setCaseNumber(admissionInfo.getCaseNumber());
        record.setItemNumber(admissionInfo.getItemNumber());
        record.setCaseTitle(admissionInfo.getCaseTitle());
        record.setDocumentTitle(admissionInfo.getDocumentTitle());
        record.setDateTime(admissionInfo.getDateTime());
        record.setResponsiblePerson(admissionInfo.getResponsiblePerson());
        record.setSpecification(admissionInfo.getSpecification());
        record.setItemCount(admissionInfo.getItemCount());
        record.setPageCount(admissionInfo.getPageCount());
        record.setRetentionPeriod(admissionInfo.getRetentionPeriod());
        record.setConfidentialityLevel(admissionInfo.getConfidentialityLevel());
        record.setDisclosureAttribute(admissionInfo.getDisclosureAttribute());
        record.setOpenFlag(admissionInfo.getOpenFlag());
        record.setRemark(admissionInfo.getRemark());
        record.setKeywords(admissionInfo.getKeywords());
        record.setStorageLocation(admissionInfo.getStorageLocation());
        record.setCataloger(admissionInfo.getCataloger());
        record.setCatalogDate(admissionInfo.getCatalogDate());
        record.setArchivingUnit(admissionInfo.getArchivingUnit());
        record.setArchiver(admissionInfo.getArchiver());
        record.setArchiveTime(admissionInfo.getArchiveTime());
        record.setElectronicDocument(admissionInfo.getElectronicDocument());
        record.setElectronicDocumentMetadata(admissionInfo.getElectronicDocumentMetadata());
        record.setNotes(admissionInfo.getNotes());
    }

    @ApiOperation("导入失败记录分页查询")
    @GetMapping("/getImportDataPage")
    public R<Page<ImportFailLog>> getImportDataPage(
            @RequestParam(defaultValue = "0") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(required = false) String startTime,
            @RequestParam(required = false) String endTime) throws ParseException {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startDate = startTime != null ? sdf.parse(startTime) : null;
        Date endDate = endTime != null ? sdf.parse(endTime) : null;
        Page<ImportFailLog> importDataPage = admissionInfoService.getImportDataPage(pageNum, pageSize, startDate, endDate);
        return R.suc(importDataPage);
    }


    //批量修改信息
    @ApiOperation("批量修改状态")
    @PostMapping("/batchUpdateAdmissionInfo")
    public R batchUpdateAdmissionInfo(@RequestBody AdmissionInfoReqVo admissionInfoReqVo) {
        // 参数校验
        if (CollectionUtils.isEmpty(admissionInfoReqVo.getAdmissionInfoList())) {
            return R.error("9999", "请选择需要移交的数据");
        }
        admissionInfoService.batchUpdateAdmissionInfo(admissionInfoReqVo);
        return R.suc();
    }

    @PostMapping("/approval")
    public R approval(@RequestBody AdmissionInfoReqVo admissionInfoReqVo) {
        // 参数校验
        if (CollectionUtils.isEmpty(admissionInfoReqVo.getAdmissionInfoList())) {
            return R.error("9999", "请选择需要审批的数据");
        }

        if (StringUtils.isBlank(admissionInfoReqVo.getTransferState())) {
            return R.error("9999", "审批状态不能为空");
        }

        try {
            // 2. 业务处理
            academicInfoService.approval(admissionInfoReqVo.getAdmissionInfoList(),
                    admissionInfoReqVo.getTransferState(), admissionInfoReqVo.getOfficeId(), admissionInfoReqVo.getBelonging(), admissionInfoReqVo.getTransferRemarks(),admissionInfoReqVo.getSource());
            return R.suc();
        } catch (IllegalArgumentException e) {
            return R.error("9999", e.getMessage());
        } catch (Exception e) {
            log.error("审批处理异常", e);
            return R.error("9999", "审批处理失败");
        }
    }


    //    导入记录列表查询
    @ApiOperation("导入失败记录分页查询")
    @GetMapping("/getImportPage")
    public R<?> getImportPage(
            @RequestParam(defaultValue = "0") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(required = false) String massage,
            @RequestParam(required = false) String name,
            @RequestParam(required = true) String importType,
            @RequestParam(required = false) String xueHao,
            @RequestParam(required = false) String templateId
    ) throws ParseException {


        IPage<ImportFailLog> importPage = admissionInfoService.getImportPage(pageNum, pageSize,massage, name, xueHao, importType,templateId);
        return R.suc(importPage);
    }


    //    导入记录新增接口
    @PostMapping("/importLogAdd")
    public R<?> importLogAdd(@RequestBody ImportFailLog param) {
        if (StringUtils.isEmpty(param.getImportType())) {
            R.error().setMsg("导入类型不能为空");
        }
        int i = admissionInfoService.importLogAdd(param);
        if (i == 1) {
            return R.suc(i);
        } else if (i == -1) {
            R.error().setMsg("新增失败,导入类型不能为空");
        }
        return R.error().setMsg("新增失败");
    }
}

